﻿using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace Common.Modules
{
    public class PdfTableCss
    {
        public CellCss TitleCellCss { get; set; }

        /// <summary>
        /// 多行数据，背景颜色循环设置
        /// </summary>
        public CellCss[] BodyCellCsses { get; set; }

        public int Alignment { get; set; }

        public float? SpacingBefore { get; set; }

        public float? SpacingAfter { get; set; }

    }

    public class CellCss
    {
        /// <summary>
        /// 多行数据，背景颜色循环设置
        /// </summary>
        public Font Font { get; set; }

        public BaseColor BackGroundColor { get; set; }

        public int Alignment { get; set; }

        public float? PaddingTop { get; set; }

        public float? PaddingBottom { get; set; }

        public int? Border { get; set; }

        public BaseColor BorderColor { get; set; }
    }

    public class ParagraphCss
    {
        private Font _font;

        public Font Font
        {
            get
            {
                if (_font == null)
                {
                    return FontFactory.GetFont("STSONG", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 10, Font.BOLD, BaseColor.BLACK);
                }
                return _font;
            }
            set { _font = value; }
        }

        private int? _alignment;

        public int? Alignment
        {
            get
            {
                if (_alignment == null)
                {
                    return Element.ALIGN_LEFT;
                }
                return _alignment;
            }
            set { _alignment = value; }
        }

        public float? SpaceBefore { get; set; }

        public float? SpaceAfter { get; set; }

    }

    public class ImageCss
    {
        private int? _alignment;

        public int? Alignment
        {
            get
            {
                if (_alignment == null)
                {
                    return Element.ALIGN_CENTER;
                }
                return _alignment;
            }
            set { _alignment = value; }
        }

        public float? Height { get; set; }

        public float? Width { get; set; }
    }

    public class PdfElementGenerater
    {
        private const string TempPdfFileName = "tmp.pdf";

        private string PdfFillFullName;

        private static string PrinterName;


        private const float LabelFontSize = 17;

        internal float ListRowSpace = 5;

        // 标题字体
        private readonly Font _titleFont;

        // 封面目录楷体
        private readonly Font _kaitiFont;
        // 封面患者姓名字体
        private readonly Font _coverCustomerNameFont;
        // 科室名称字体
        private readonly Font _deptNameFont;

        public PdfElementGenerater()
        {
            FontFactory.RegisterDirectory(AppDomain.CurrentDomain.BaseDirectory + "Fonts");
            _coverCustomerNameFont = FontFactory.GetFont(
                "STSONG", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 10, Font.BOLD, BaseColor.BLACK);
            _titleFont = FontFactory.GetFont(
                "SIMHEI", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 10, Font.NORMAL, BaseColor.BLACK);
            _kaitiFont = FontFactory.GetFont(
                "STKAITI", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 10, Font.NORMAL, BaseColor.BLACK);
            _deptNameFont = FontFactory.GetFont(
                "SIMHEI", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 10, Font.NORMAL, BaseColor.BLACK);
        }

        public PdfPTable MakeTable(Document doc, PdfTableCss pdfTableCss, float[] widths)
        {
            var pdfPTable = new PdfPTable(widths.Length)
                                {
                                    TotalWidth = doc.Right - doc.Left,
                                    SpacingBefore = pdfTableCss.SpacingBefore.HasValue ? pdfTableCss.SpacingBefore.Value : 1,
                                    SpacingAfter = pdfTableCss.SpacingAfter.HasValue ? pdfTableCss.SpacingAfter.Value : 1
                                };
            pdfPTable.SetWidths(widths);
            pdfPTable.LockedWidth = true; //必须锁定宽度，否则修改无效
            return pdfPTable;
        }

        public void AddCellToTable(PdfPTable table, string message, CellCss cellCss)
        {
            var pCellLabel = new PdfPCell(new Phrase(message, cellCss.Font))
            {
                BorderColor = cellCss.BorderColor,
                BackgroundColor = cellCss.BackGroundColor,
                HorizontalAlignment = cellCss.Alignment,
                VerticalAlignment = Element.ALIGN_MIDDLE,
                PaddingTop = cellCss.PaddingTop.HasValue ? cellCss.PaddingTop.Value : 3,
                PaddingBottom = cellCss.PaddingBottom.HasValue ? cellCss.PaddingBottom.Value : 3,
                Border = cellCss.Border ?? Rectangle.NO_BORDER
            };
            table.AddCell(pCellLabel);
        }

        public void AddSimpleParagraph(Document doc, string message, ParagraphCss coverCss)
        {
            var p = new Paragraph(message, coverCss.Font)
            {
                Alignment = coverCss.Alignment.Value,
                SpacingBefore = coverCss.SpaceBefore.HasValue ? coverCss.SpaceBefore.Value : 0,
                SpacingAfter = coverCss.SpaceAfter.HasValue ? coverCss.SpaceAfter.Value : 5,
            };
            doc.Add(p);
        }

        public void AddImage(Document doc, System.Drawing.Image image, ImageCss imageCss)
        {
            var pdfImage = iTextSharp.text.Image.GetInstance(image, BaseColor.WHITE);
            pdfImage.Alignment = imageCss.Alignment != null ? imageCss.Alignment.Value : Element.ALIGN_CENTER;

            float docHeight = doc.Top - doc.TopMargin;
            float docWidth = doc.Right - doc.Left;
            float height = imageCss.Height == null ?
                (image.Height > docHeight ? docHeight : image.Height) :
                (imageCss.Height > docHeight ? docHeight : imageCss.Height.Value);
            float width = imageCss.Width == null ?
                (image.Width > docWidth ? docWidth : image.Width) :
                (imageCss.Width > docWidth ? docWidth : imageCss.Width.Value);
            //图片原始大小
            pdfImage.ScaleToFit(width, height);
            doc.Add(pdfImage);
        }

        /// <summary>
        /// 添加虚线分割线
        /// </summary>
        /// <param name="pdfWriter"></param>
        /// <param name="doc"></param>
        /// <param name="yOffset">虚线相对于当前Y坐标的偏移量，正数表示上移，负数表示下移</param>
        public void InsertDashedLine(PdfWriter pdfWriter, Document doc, float yOffset = 0)
        {
            var cb = pdfWriter.DirectContent;
            cb.SetRGBColorStroke(0, 0, 0);
            cb.SetLineWidth(1.0f);
            cb.MoveTo(doc.Left, pdfWriter.GetVerticalPosition(false) + yOffset);
            cb.LineTo(doc.Right, pdfWriter.GetVerticalPosition(false) + yOffset);
            cb.SetLineDash(1, 3, 0);
            cb.Stroke();
            cb.SetLineDash(1, 0, 0);
        }

        /// <summary>
        /// 运行某个程序
        /// </summary>
        /// <param name="executable"></param>
        /// <param name="arguments"></param>
        public void RunExecutable(string executable, string arguments)
        {
            var starter = new ProcessStartInfo(executable, arguments) { CreateNoWindow = true, RedirectStandardOutput = true, UseShellExecute = false };
            var process = new Process { StartInfo = starter };
            process.Start();
            var buffer = new StringBuilder();
            using (var reader = process.StandardOutput)
            {
                var line = reader.ReadLine();
                while (line != null)
                {
                    buffer.Append(line);
                    buffer.Append(Environment.NewLine);
                    line = reader.ReadLine();
                    Thread.Sleep(100);
                }
            }
            if (process.ExitCode != 0)
            {
                throw new Exception(string.Format(@"""{0}"" exited with ExitCode {1}. Output: {2}", executable, process.ExitCode, buffer));
            }
        }

    }
}